package com.yxt.qmgf.snake.task;

import com.yxt.qmgf.snake.constant.Const;
import com.yxt.qmgf.snake.constant.Direction;
import com.yxt.qmgf.snake.ctrl.snakeInfoController;
import com.yxt.qmgf.snake.view.SnakePane;
import com.yxt.qmgf.snake.vo.SnakeCell;
import javafx.concurrent.Task;
import javafx.scene.paint.Color;

import java.util.Random;

public class MoveTask extends Task<Integer> {

    private SnakePane pane;
    private Random random = new Random();
    public MoveTask(SnakePane pane) {
        this.pane = pane;
    }

    public volatile static boolean isForceCancel = false;

    public volatile static boolean isOverBound = false;
    public volatile static boolean isEatItSelf = false;
    private int currentSize = 0;

    public static void reDetect() {
        isOverBound = false;
        isEatItSelf = false;
    }

    private boolean isEat(SnakeCell cell) {
        if (cell.getX() == pane.getFood().getX() && cell.getY() == pane.getFood().getY()) {

            pane.setScore(pane.getScore() + pane.getScorv());
            return true;
        }
        return false;
    }

    private boolean isEatItSelf() {
        SnakeCell first = Const.SNAKE_CELL_LIST.getFirst();
        for (int i = 1; i < Const.SNAKE_CELL_LIST.size(); i++) {
            if (first.getX() == Const.SNAKE_CELL_LIST.get(i).getX() && first.getY() == Const.SNAKE_CELL_LIST.get(i).getY()) {
                return true;
            }
        }
        return false;
    }

    @Override
    protected Integer call() throws Exception {

        while (!isCancelled()) {

            if (Const.SNAKE_CELL_LIST.getFirst().getX() < 50 || Const.SNAKE_CELL_LIST.getFirst().getY() < 50 ||
                    Const.SNAKE_CELL_LIST.getFirst().getX() > 770 || Const.SNAKE_CELL_LIST.getFirst().getY() > 770) {
                isOverBound = true;
                continue;
            }

            if (Const.SNAKE_CELL_LIST.size() > 3 && isEatItSelf()) {
                isEatItSelf = true;
                continue;
            }

            SnakeCell cell;
            switch (snakeInfoController.current_direction) {

                case Direction.L:
                    cell = Const.SNAKE_CELL_LIST.removeLast();
                    cell.setX(Const.SNAKE_CELL_LIST.getFirst().getX() - 20);
                    cell.setY(Const.SNAKE_CELL_LIST.getFirst().getY());
                    Const.SNAKE_CELL_LIST.addFirst(cell);
                    if (isEat(cell)) {
                        controlFood(Direction.L);
                    }
                    break;
                case Direction.R:
                    cell = Const.SNAKE_CELL_LIST.removeLast();
                    cell.setX(Const.SNAKE_CELL_LIST.getFirst().getX() + 20);
                    cell.setY(Const.SNAKE_CELL_LIST.getFirst().getY());
                    Const.SNAKE_CELL_LIST.addFirst(cell);
                    if (isEat(cell)) {
                        controlFood(Direction.R);
                    }
                    break;

                case Direction.U:
                    cell = Const.SNAKE_CELL_LIST.removeLast();
                    cell.setY(Const.SNAKE_CELL_LIST.getFirst().getY() - 20);
                    cell.setX(Const.SNAKE_CELL_LIST.getFirst().getX());
                    Const.SNAKE_CELL_LIST.addFirst(cell);
                    if (isEat(cell)) {
                        controlFood(Direction.U);
                    }
                    break;
                case Direction.D:
                    cell = Const.SNAKE_CELL_LIST.removeLast();
                    cell.setY(Const.SNAKE_CELL_LIST.getFirst().getY() + 20);
                    cell.setX(Const.SNAKE_CELL_LIST.getFirst().getX());
                    Const.SNAKE_CELL_LIST.addFirst(cell);

                    if (isEat(cell)) {
                        controlFood(Direction.D);
                    }
                    break;
            }
            if (Const.SNAKE_CELL_LIST.size() != currentSize && Const.SNAKE_CELL_LIST.size() % 5 == 0){
                currentSize = Const.SNAKE_CELL_LIST.size();
                pane.setSpeed(pane.getSpeed() - 1);
            }
            int currentSpeed = pane.getSpeed();
            pane.repaint();
            Thread.sleep(currentSpeed);
        }
        return null;
    }

    private void controlFood(int dir) {
        SnakeCell food = pane.getFood();
        switch (dir) {
            case Direction.L:
                food.setX(Const.SNAKE_CELL_LIST.getFirst().getX() + 20);
                break;
            case Direction.R:
                food.setX(Const.SNAKE_CELL_LIST.getFirst().getX() - 20);
                break;
            case Direction.D:
                food.setY(Const.SNAKE_CELL_LIST.getFirst().getY() - 20);
                break;
            case Direction.U:
                food.setY(Const.SNAKE_CELL_LIST.getFirst().getY() + 20);
                break;
        }

        food.setColor(Color.BLACK);
        Const.SNAKE_CELL_LIST.addLast(food);

        // 食物
        SnakeCell food1 = createFood();
        while (checkIsOnSnakeBody(food1)) {
            food1 = createFood();
        }
        pane.setFood(food1);
    }

    private boolean checkIsOnSnakeBody(SnakeCell food) {
        for (SnakeCell cell : Const.SNAKE_CELL_LIST) {
            if (cell.getY() == food.getY() && cell.getX() == food.getX())
                return true;
        }
        return false;
    }

    private SnakeCell createFood() {
        int x = random.nextInt(770);
        x = x - x % 20;
        if (x / 10 % 10 % 2 == 0)
            x = x - 10;
        if (x < 50)
            x = 50;
        int y = random.nextInt(770);
        y = y - y % 20;
        if (y / 10 % 10 % 2 == 0)
            y = y - 10;
        if (y < 50)
            y = 50;
        return new SnakeCell(x, y, Const.cellLen, Color.GREEN, "rectangle");
    }

}
